package com.hershel.userservice.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.WeakKeyException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;
import java.util.function.Function;

@Component
public class JwtUtil {

    /**
     * 日志对象
     */
    private final static Logger LOGGER = LoggerFactory.getLogger(JwtUtil.class);

    /**
     * // 使用HS256算法和密钥生成器生成密钥
     */
    private static final Key KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    /**
     * 发行者信息
     */
    private static final String ISSUER = "AuthServer-hershel";


    /**
     * 应该设置为更安全的密钥
     */
    private static final String SECRET_KEY = "hershelqaz123WSX456edc789RFVtgbYHNujmIKOLPbvdsfsddsfewrwesdfsd";

    /**
     * 1小时过期时间，单位为毫秒
     */
    private static final long EXPIRATION_TIME = 3600000;


    /**
     * 获取用户名
     *
     * @param token token
     * @return username
     */
    public static String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }

    /**
     * 获取过期时间
     *
     * @param token token
     * @return 过期时间
     */
    public static Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    public static <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }

    private static Claims extractAllClaims(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(KEY) // 设置密钥来验证签名
                .build()
                .parseClaimsJws(token) // 解析token获取claims部分
                .getBody(); // 获取claims主体部分
    }

    /**
     * 检查token是否过期
     *
     * @param token
     * @return
     */
    private static Boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }

    /**
     * 生成token的方法
     *
     * @param username 用户名
     * @return token
     */
    public static String generateToken(String username) {
        LOGGER.info("username:{}", username);
        String token = null;
        try {
            // 构建器用于创建JWTs。设置Payload。这里我们设置JWT的主题（即用户）和发行者。
            token = Jwts.builder()
                    // 设置主题为username，通常是用户名或用户ID。
                    .setSubject(username)
                    // 设置发行者信息。这有助于在验证时识别发行者。
                    .setIssuer(ISSUER)
                    // 设置发行时间。这是可选的，但通常用于跟踪何时创建了令牌。
                    .setIssuedAt(new Date(System.currentTimeMillis()))
                    // 设置过期时间。这是必需的，以防止令牌无限期地有效。在这里，我们将其设置为当前时间加上一小时（3600000毫秒）。你可以根据需要调整这个值。例如，如果你想让令牌有效期为一天，你可以将EXPIRATION_TIME设置为86400000（即24小时乘以60分钟乘以60秒乘以1000毫秒）。 记住，过期时间是从发行时间开始计算的。因此，如果你的令
                    .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                    // 设置签名算法和密钥
                    .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                    // 生成Token字符串
                    .compact();
        } catch (WeakKeyException e) {
            LOGGER.error("密钥长度不够。");
        }
        return token;
    }
}
